﻿using System;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;

namespace MingYuanYun.StructuredLog.Abstractions
{
    public class MyStructuredLog
    {
        private static string _serverIp = string.Empty;
        private static string _server = string.Empty;

        //错误信息
        public ErrorMessage Message { get; set; }

        private readonly MyLoggerOptions _options;

        public MyStructuredLog(MyLoggerOptions options)
        {
            this._options = options;
            this.ID = Guid.NewGuid().ToString();

            PrepareLog();
        }
         

        public string ID { get; set; }

        /// <summary>
        /// ms,耗时
        /// </summary>
        public string Time { get; set; } = "-";

        /// <summary>
        /// 产品代码
        /// </summary>
        public string Production { get; set; } = "-";

        /// <summary>
        /// 组件名称
        /// </summary>
        public string App { get; set; } = "-";

        public string Server { get; set; } = "-";

        public string ServerIP { get; set; } = "-";

        public string Level { get; set; }

        public object Description { get; set; } = "-";

        public string ClassName { get; set; } = "-";

        public string FunctionName { get; set; } = "-";

        /// <summary>
        /// user 登陆 app 的用户
        /// </summary>
        public string User { get; set; } = "-";

        public int Duration { get; set; } = -1;

        /// <summary>
        /// 记录操作类型，对于WebApi可以是post、get等，对数据库可能是Update等
        /// </summary>
        public string Action { get; set; } = "-";

        /// <summary>
        /// 自定义字段，以Json存储
        /// </summary>
        public string CustomizedValve { get; set; } = "-";

        /// <summary>
        /// Json 记录上下文信息
        /// </summary>
        public string Context { get; set; } = "-";

        /// <summary>
        /// app 程序版本
        /// </summary>
        public string Version { get; set; } = "-";

        public string AppPath { get; set; } = "-";

        public string ServerOS { get; set; } = "-";

        public int ThreadID { get; set; }

        public string InnerException { get; set; }

        private void PrepareLog()
        {
            this.GetInternalIp();
            this.SetOccurTime();
            this.SetThreadId();
            this.SetFunctionName();
            this.SetRuntimeEnv();

            this.App = _options.AppName;
            this.Production = _options.ProductCode;
        }

        private void SetFunctionName()
        {
            try
            {
                //can not get these info in .net core
                this.FunctionName = "-";
                this.ClassName = "-";
            }
            catch (Exception)
            {
                this.FunctionName = "-";
                this.ClassName = "-";
            }
        }

        // 获取内网IP以及主机名，缓存正确获取的信息
        private void GetInternalIp()
        {
            if (!string.IsNullOrEmpty(_serverIp))
            {
                this.ServerIP = _serverIp;
                this.Server = _server;

                return;
            }

            try
            {
                var host = Dns.GetHostEntryAsync(Dns.GetHostName()).Result;

                foreach (var ip in host.AddressList)
                {
                    if (ip.AddressFamily.ToString() == "InterNetwork")
                    {
                        this.ServerIP = ip.ToString();
                        this.Server = host.HostName;

                        _serverIp = ip.ToString();
                        _server = host.HostName;

                        break;
                    }
                }
            }
            catch (Exception)
            {
                this.ServerIP = "Can not get server Ip.";
                this.Server = "Can not get server Name.";
            }
        }

        private void SetRuntimeEnv()
        {
            try
            {
                this.ServerOS = RuntimeInformation.OSDescription;
            }
            catch (Exception)
            {
                this.ServerOS = "Can not get Server OS.";
            }
        }

        private void SetOccurTime()
        {
            this.Time = DateTime.Now.ToString("O");
        }

        private void SetThreadId()
        {
            this.ThreadID = Thread.CurrentThread.ManagedThreadId;
        }
    }
}
